import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

enum WrapMode { word, character }

class TextController extends ChangeNotifier {
  String text;
  final TextStyle style;
  final WrapMode wrapMode;
  final double? maxWidth;
  final String? fontFamily;
  final FontWeight? fontWeight;
  final FontStyle? fontStyle;
  double? wordSpacing;
  List<ChipLayoutInfo> _chipLayoutInfo = [];
  List<LineInfo> _lineInfo = [];
  // Store multiple ranges with their colors
  final Map<Range, Color> _rangeColorMap = {};

  TextController(
      {required this.text,
      required this.style,
      required this.wrapMode,
      this.maxWidth,
      this.fontFamily,
      this.fontWeight,
      this.fontStyle,
      this.wordSpacing});

  List<ChipLayoutInfo> get chipLayoutInfo => _chipLayoutInfo;
  List<LineInfo> get lineInfo => _lineInfo;

  // 计算文本布局信息并缓存
  void calculateTextLayout() {
    _chipLayoutInfo.clear();
    final textPainter = TextPainter(
      text: TextSpan(text: text, style: style),
      textDirection: TextDirection.ltr,
      maxLines: null,
      textWidthBasis: TextWidthBasis.parent,
    );

    textPainter.layout(maxWidth: maxWidth ?? double.infinity);

    if (wrapMode == WrapMode.word) {
      _calculateWordWrapLayout(textPainter);
    } else {
      _calculateCharacterWrapLayout(textPainter);
    }
    notifyListeners();
    for (var info in chipLayoutInfo) {
      print(info);
    }
  }

  // 按单词换行计算布局
  void _calculateWordWrapLayout(TextPainter textPainter) {
    double currentX = 0;
    double currentY = 0;
    final lineHeight = style.fontSize! * (style.height ?? 1.0);

    final words = text.split(' ');
    int startIndex = 0;
    // 空白符号的宽度计算
    final wordNone = TextPainter(
      text: TextSpan(text: " ", style: style),
      textDirection: TextDirection.ltr,
    );
    if ((wordSpacing ?? 0) <= 0) {
      wordNone.layout();
    }

    for (var word in words) {
      final wordPainter = TextPainter(
        text: TextSpan(text: word, style: style),
        textDirection: TextDirection.ltr,
      );
      wordPainter.layout();

      // 判断是否换行
      if (currentX + wordPainter.width > (maxWidth ?? double.infinity)) {
        currentX = 0;
        currentY += lineHeight;
      }

      // 创建ChipLayoutInfo
      final wordRange = Range(startIndex, startIndex + word.length - 1);
      final wordLayoutInfo = ChipLayoutInfo(
        text: word,
        offset: Offset(currentX, currentY),
        size: wordPainter.size,
        range: wordRange,
        childs: _createCharChipLayoutInfo(word, currentX, currentY),
      );

      _chipLayoutInfo.add(wordLayoutInfo);

      currentX += wordPainter.width + (wordSpacing ?? wordNone.width); // Add space between words
      startIndex += word.length + 1;
    }
  }

  // 按字符换行计算布局
  void _calculateCharacterWrapLayout(TextPainter textPainter) {
    double currentX = 0;
    double currentY = 0;
    final lineHeight = style.fontSize! * (style.height ?? 1.0);

    int startIndex = 0;
    final characters = text.split('');

    for (var char in characters) {
      textPainter.text = TextSpan(text: char, style: style);
      textPainter.layout();

      if (currentX + textPainter.width > (maxWidth ?? double.infinity)) {
        currentX = 0;
        currentY += lineHeight;
      }

      // 创建ChipLayoutInfo
      final charRange = Range(startIndex, startIndex);
      final charLayoutInfo = ChipLayoutInfo(
        text: char,
        offset: Offset(currentX, currentY),
        size: textPainter.size,
        range: charRange,
      );

      _chipLayoutInfo.add(charLayoutInfo);

      currentX += textPainter.width;
      startIndex++;
    }
  }

  // 创建字符级别的ChipLayoutInfo
  List<ChipLayoutInfo> _createCharChipLayoutInfo(String word, double startX, double startY) {
    final textPainter = TextPainter(
      text: TextSpan(text: word, style: style),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();

    double currentX = startX;
    final charChipLayoutInfo = <ChipLayoutInfo>[];

    for (int i = 0; i < word.length; i++) {
      final char = word[i];
      final charPainter = TextPainter(
        text: TextSpan(text: char, style: style),
        textDirection: TextDirection.ltr,
      );
      charPainter.layout();

      final charRange = Range(i, i);
      final charLayoutInfo = ChipLayoutInfo(
        text: char,
        offset: Offset(currentX, startY),
        size: charPainter.size,
        range: charRange,
      );

      charChipLayoutInfo.add(charLayoutInfo);
      currentX += charPainter.width;
    }

    return charChipLayoutInfo;
  }

  // 根据给定的原始字符串范围获取布局信息
  List<ChipLayoutInfo> getRangeLayoutInfo(Range targetRange) {
    if (wrapMode == WrapMode.word) {
      var startIndex = -1;
      var endIndex = -1;
      for (var index = 0; index < _chipLayoutInfo.length; index++) {
        var item = _chipLayoutInfo[index];
        // 1. 在单词内
        // 2. 起点刚好是空格，取距离空格第一个单词
        if (_positionAtInfo(targetRange.start, item)) {
          startIndex = index;
        } else if (item.range.start > targetRange.start && startIndex == -1) {
          startIndex = index;
        }
        if (_positionAtInfo(targetRange.end, item)) {
          endIndex = index;
        } else if (item.range.end > targetRange.end && startIndex == -1) {
          endIndex = index;
        }
      }
      if (endIndex < startIndex || endIndex < 0 || startIndex < 0) return [];
      if (endIndex == startIndex) return [_chipLayoutInfo[endIndex]];
      return _chipLayoutInfo.sublist(startIndex, endIndex + 1);
    }

    return [];
  }

  bool _positionAtInfo(int position, ChipLayoutInfo info) {
    return position >= info.range.start && position <= info.range.end;
  }

// 设置range 下划线并指定颜色
  void setLineColorWithRange(Range range, {Color? color}) {
    if (color != null) {
      // Add or update the range-color mapping
      _rangeColorMap[range] = color;
    } else {
      // Remove the range if color is null
      _rangeColorMap.remove(range);
    }

    // Clear existing line info
    _lineInfo.clear();

    // Process each range-color pair
    _rangeColorMap.forEach((rangeKey, colorValue) {
      // Get affected chips for this range
      final affectedChips = getRangeLayoutInfo(rangeKey);
      if (affectedChips.isNotEmpty) {
        // Get underlined ranges for these chips
        final rangeLines = getUnderlinedRanges(affectedChips, rangeKey, underlineColor: colorValue);
        _lineInfo.addAll(rangeLines);
      }
    });

    notifyListeners();
  }

  // 计算下划线的起点和终点，并返回 LineInfo
  List<LineInfo> getUnderlinedRanges(List<ChipLayoutInfo> chipLayoutInfo, Range range,
      {Color? underlineColor}) {
    List<LineInfo> lineInfos = [];
    var datas = <double, List<ChipLayoutInfo>>{};

    // 1. 根据Y坐标分组
    for (var chip in chipLayoutInfo) {
      if (datas.containsKey(chip.offset.dy)) {
        datas[chip.offset.dy]!.add(chip);
      } else {
        datas[chip.offset.dy] = [chip];
      }
    }

    // 2. 处理每一行的文本
    for (var entry in datas.entries) {
      List<ChipLayoutInfo> lineChips = entry.value;

      // 按X坐标排序，确保从左到右处理
      lineChips.sort((a, b) => a.offset.dx.compareTo(b.offset.dx));
      // 获取起点
      var start = _getOffsetForPosition(lineChips.first, range.start);
      // 获取终点
      ChipLayoutInfo last = lineChips.last;
      // 获取同行符合条件的一个
      for (var item in lineChips) {
        if (item.range.start <= range.end) {
          last = item;
        }
      }
      var end = _getOffsetForPosition(last, range.end);
      lineInfos.add(LineInfo(
        startOffset: start,
        endOffset: end,
        color: underlineColor,
      ));
    }

    return lineInfos;
  }

  Offset _getOffsetForPosition(ChipLayoutInfo info, int index) {
    if ((info.childs?.length ?? 0) == 0) return info.offset;
    if (index >= info.childs!.last.range.start + info.range.start) {
      return Offset(info.childs!.last.offset.dx + info.childs!.last.size.width, info.childs!.last.offset.dy);
    }
    if (index <= info.range.start) {
      return info.childs!.first.offset;
    }
    for (var item in info.childs!) {
      if (index == info.range.start + item.range.start) {
        return item.offset;
      }
    }
    return Offset.zero;
  }

  void updateText(String text) {
    this.text = text;
    calculateTextLayout();
  }

  Color? getColorAtPosition(int position) {
    for (var entry in _rangeColorMap.entries) {
      if (position >= entry.key.start && position <= entry.key.end) {
        return entry.value;
      }
    }
    return null;
  }

  // Remove underline for a specific range
  void removeLineForRange(Range range) {
    setLineColorWithRange(range, color: null);
  }

  // Clear all underlines
  void clearAllUnderlines() {
    _rangeColorMap.clear();
    _lineInfo.clear();
    notifyListeners();
  }

// Get all active ranges
  List<Range> get activeRanges => _rangeColorMap.keys.toList();
  @override
  void dispose() {
    _rangeColorMap.clear();
    super.dispose();
  }
}

class ChipLayoutInfo {
  final String text;
  final Offset offset;
  final Size size;
  final Range range;
  final List<ChipLayoutInfo>? childs;

  ChipLayoutInfo({
    required this.text,
    required this.offset,
    required this.size,
    required this.range,
    this.childs,
  });
  @override
  String toString() {
    return "$text, offset: $offset, size: $size, range: ${range.start}-${range.end}";
  }
}

class Range {
  final int start; // 范围的起始位置
  final int end; // 范围的结束位置

  Range(this.start, this.end);
}

class LineInfo {
  final Offset startOffset; // 线段的起点
  final Offset endOffset; // 线段的终点
  final double width; // 线段的宽度
  final Color? color; // 线段的颜色

  LineInfo({
    required this.startOffset,
    required this.endOffset,
    this.width = 2,
    this.color,
  });

  @override
  String toString() {
    return "$startOffset -> $endOffset, width: $width";
  }
}
